import logging

from world.overworld.landmarks import OverworldLandmarks
from world.overworld.tiles import OverworldTiles

MAP_ASCII = """\
≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈.λ.......≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈...ǂ...ǂ.λ.ǂ...λ.λ.λ.λ.(?).ǂ.ǂ.λ.ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈.ǂ.ǂ.λ.λ.ǂ╔═[∆]λ.λ.λ.≈≈≈≈λ.ǂ.ǂ.ǂ.λ.ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈...ǂ.ǂ.λ.ǂ.║.ǂ.λ.λ.λ.λ.λ.λ.λ.ǂ.λ.ǂ.λ.ǂ.ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈.λ.....ǂ.λ.ǂ╚═╗ǂ...λ(?)λ.λ.λ...ǂ.λ.ǂ...ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈≈≈.ǂ.λ.......ǂ.....║...λ.λ.λ.▒.λ...λ...ǂ.λ.ǂ.λ.ǂ.λ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈≈.ǂ.λ..............╠═══╗..≈.λ.▒.▒.▒.▒.ǂ...ǂ.λ.λ.λ.λ...λ.≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈.ǂ...λ.............║...╚═Ξ═╗.▒...▒...ǂ.ǂ...λ.λ.λ.λ.ǂ...λ.≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈≈.λ...ǂ........╔═══╝....≈≈.║▒.▒.▒.▒..╔═══[∆]λ.λ.λ.λ.ǂ.λ.≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈.λ.ǂ.......╔══[∆].......≈≈.╚═╗.▒.▒...║.....ǂ.λ...λ.λ.λ.≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈.λ...λ..╔═════╝..........≈≈≈....╚═══════╝..ǂ...........▒.▒.≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈...λ.λ...║...............≈≈..........ǂ...........ǂ.....▒.ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈.λ.λ....║.≈≈≈≈≈..ǂ.......≈.......ǂ.ǂ...................≈≈≈(?)≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈.λ.λ...║≈≈≈▒≈≈≈..ǂ.....≈.....ǂ.ǂ.ǂ.ǂ.ǂ.ǂ.......≈≈≈≈..ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈...λ....║..▒.▒.ǂ........≈≈...ǂ.ǂ.ǂ.ǂ.ǂ..........≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈...λ.λ.╚═╗.▒.▒.......≈≈≈...ǂ.ǂ.ǂ.ǂ.ǂ...ǂ...........≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈.λ.λ...λ..║..........≈...≈.ǂ.ǂ╔═══[∆]ǂ.ǂ.ǂ...........≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈...λ.λ.....║.....ǂ...≈≈.╔══Ξ═══╝.ǂ.ǂ.ǂ.ǂ.ǂ.............≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈...λ.λ.λ.λ....║(?).........║...≈.ǂ.ǂ.ǂ.ǂ.ǂ.ǂ.ǂ.▒.......ǂ.ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈.λ.λ.λ...λ.....╠═══════╦════╝..ǂ.≈.ǂ.ǂ.ǂ.ǂ.ǂ.ǂ...ǂ.▒.....ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈(?).λ.λ.λ.λ..║.......║........ǂ.≈.ǂ.ǂ.ǂ.ǂ.ǂ.ǂ.....▒.........≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈.λ.λ[∆]╗.λ...║.......║.........≈≈≈≈..ǂ...ǂ...▒...▒...........≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈.λ...λ╚═════╝.......╚══╗.....≈≈≈≈≈.......ǂ...▒..[∆]...≈≈≈≈.....≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈.λ.λ.λ.λ..............║.........≈≈.........▒............≈≈.....≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈.λ...λ.λ.ǂ...........╚══╗.......≈≈............╔══════╗.≈≈≈...≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈...λ...λ.ǂ.......ǂ.......║........≈≈...........║......║...≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈.....λ.λ.....ǂ.ǂ......║....ǂ.ǂ≈≈............║...≈≈.╚[∆]≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈.λ.λ.......ǂ.ǂ.ǂ.....║.....ǂ≈≈.............║....≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈.λ.λ...λ...ǂ..........╚═══════╦═════════════╣......≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈.ǂ.≈≈≈...λ...λ...ǂ...............ǂ[∆]............║...........≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈.ǂ.ǂ.≈≈≈...λ.λ.λ.............ǂ.≈≈≈≈≈≈≈≈≈≈.........║............≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈.ǂ.ǂ.≈≈≈≈≈..................≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈......║...............≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈.ǂ.ǂ.≈≈≈.......░..........≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈.....║..............≈≈≈≈≈≈≈≈≈≈
≈≈≈≈.ǂ.ǂ...ǂ.........░...░.........≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈....╚═══╗.........≈≈≈≈≈≈≈≈≈≈≈
≈≈≈...............░.░.░.░.........≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈.......║..........≈≈≈≈≈≈≈≈≈≈
≈≈.............░.░...░.░.░.........ǂ.≈≈≈≈≈≈≈≈≈≈≈≈..........║...........≈≈≈≈≈≈≈≈≈
≈≈≈.........░...░...░.░...........≈≈≈≈≈≈≈≈≈≈≈≈≈≈...........║....░.....≈≈≈≈≈≈≈≈≈≈
≈≈≈≈.........░...░.Ų...░.░.░.......≈≈≈.≈≈≈≈≈≈..............║...░.........≈≈≈≈≈≈≈
≈≈≈≈≈.......░.Ų(?)Ų...░.....░.......≈≈≈≈≈≈..ǂ.ǂ............║....░.░.......≈≈≈≈≈≈
≈≈≈≈≈≈.....░...Ų.Ų.░.≈.░..............≈≈≈..ǂ...............║...░.......≈≈≈≈≈≈≈≈≈
≈≈≈.........░.░.Ų.Ų.░.░.░.............ǂ.≈≈≈.......░.░......║..░.░.......≈≈≈≈≈≈≈≈
≈≈...λ.........░.░.Ų.Ų.░.░.....ǂ...ǂ.ǂ.≈≈≈.........░.░.....║...............≈≈≈≈≈
≈...λ...........░.Ų.Ų.░.░.........ǂ.ǂ.≈≈≈.........░...░....║..........≈≈≈≈≈≈≈≈≈≈
≈≈...λ.........░.Ų.Ų.░...............≈≈≈.....ǂ...░(?).....[∆]........≈≈≈≈≈≈≈≈≈≈≈
≈≈≈.λ.ǂ...........░.Ų.Ų.░.....≈≈≈.....≈≈≈.........░.░...............≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈.λ.ǂ...........░.Ų.░.......≈≈≈≈..≈≈≈≈........░.....................≈≈≈≈≈≈≈≈≈
≈≈≈.λ.λ.ǂ.............Ų.░...ǂ.....≈≈≈.ǂ.≈≈≈.............................≈≈≈≈≈≈≈≈
≈≈≈≈.λ.......................ǂ...≈≈≈≈≈≈≈≈≈.......ǂ...............ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈.........................ǂ.ǂ.ǂ.≈≈≈.........................ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈.......ǂ...................ǂ.ǂ.≈≈≈...................≈≈≈.ǂ.ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈.....ǂ.....ǂ.....ǂ.....λ.........≈≈≈...........≈≈≈≈≈≈≈≈≈.ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈.......ǂ.▒.▒.▒.........λ.....λ...≈≈≈.........≈≈≈≈≈.ǂ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈.....ǂ.▒.▒.▒.▒.▒.ǂ.......λ.λ.λ.λ...≈≈≈...........≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈.....▒...▒.▒.▒.....▒.▒.....λ...λ...≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈...▒.▒(?)▒.▒.▒.ǂ...▒.....λ...λ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈.....▒.▒.ǂ.▒.ǂ.ǂ.ǂ...........λ...≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈.ǂ.ǂ.▒.▒.▒.▒.ǂ...ǂ.......λ.λ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈.ǂ.ǂ.ǂ.▒.ǂ.▒.▒.........λ.λ.....≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈.ǂ...ǂ.............λ.λ...≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈.ǂ.ǂ.▒...▒.▒.....λ.≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈...ǂ.....▒.......≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈.ǂ.ǂ.ǂ[∆]▒...≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈.ǂ.ǂ.ǂ.......≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈.......≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈\
"""


def get_map_legend():
    overworld_tiles = OverworldTiles.values()
    map_legend = {
        tile.symbol: tile for tile in overworld_tiles
    }

    for tile in overworld_tiles:
        if tile.alt_symbols:
            for symbol in tile.alt_symbols:
                map_legend[symbol] = tile

    return map_legend


def get_landmarks():
    return {landmark.coordinates: landmark for landmark in OverworldLandmarks.values()}


class OverworldMap:
    _split_map = MAP_ASCII.splitlines()

    MAP_LEGEND = get_map_legend()
    LANDMARKS = get_landmarks()
    WIDTH = len(_split_map[0])
    HEIGHT = len(_split_map)

    _multi_char_tile_symbols = {symbol: tile for symbol, tile in MAP_LEGEND.items() if len(symbol) > 1}

    @classmethod
    def get_landmark(cls, coordinates):
        world_x, world_y = coordinates
        world_y = cls._invert_origin_y(world_y, 1)
        if world_y < 0 or world_y >= cls.HEIGHT:
            return None

        return cls.LANDMARKS.get((world_x, world_y))

    @classmethod
    def get_tile(cls, coordinates):
        world_x, world_y = coordinates
        world_y = cls._invert_origin_y(world_y, 1)
        if world_y < 0 or world_y >= cls.HEIGHT:
            return None

        symbol = cls._split_map[world_y][world_x]
        tile = cls.MAP_LEGEND.get(symbol)
        if not tile:
            tile = next(
                (
                    _tile for _symbol, _tile in cls._multi_char_tile_symbols.items()
                    if symbol in _symbol
                ), None
            )

        if not tile:
            logging.error(f"There are no known tile for coordinates {coordinates} and symbol {symbol}.")

        return tile

    @classmethod
    def get(cls, coordinates):
        landmark = cls.get_landmark(coordinates)
        if landmark:
            return landmark

        tile = cls.get_tile(coordinates)

        return tile

    @classmethod
    def get_rect_symbols(cls, world_x, world_y, width, height):
        """
        Return all symbols from the map contained within a rectangle.
        """
        symbols = [[' ' for _ in range(width)] for _ in range(height)]
        world_y = cls._invert_origin_y(world_y, height)

        for local_y in range(height):
            y = world_y + local_y
            if y < 0 or y >= cls.HEIGHT:
                continue

            row = cls._split_map[y]
            row_width = len(row)
            for local_x in range(width):
                x = world_x + local_x
                if x < 0 or x >= row_width:
                    continue

                symbol = row[x]
                symbols[local_y][local_x] = symbol

        return symbols

    @classmethod
    def _invert_origin_y(cls, world_y, height):
        """
        This method inverts the origin because the ascii map starts Top Left
        while in-game coordinates start from the bottom left.
        """
        return cls.HEIGHT - world_y - height
